import type { Editor } from "@tiptap/vue-3";

/**
 * 从编辑器中移除指定 commentId 的标记
 */
export function removeCommentMark(editor: Editor, commentId: string): void {
  const { state } = editor;
  const commentMarkType = state.schema.marks.comment;
  if (!commentMarkType) return;

  const { tr } = state;
  const ranges: Array<{ from: number; to: number }> = [];

  // 遍历文档，找到所有带有该commentId的标记范围
  state.doc.descendants((node, pos) => {
    if (node.isText) {
      // 检查该文本节点的所有marks
      node.marks.forEach((mark) => {
        if (
          mark.type.name === "comment" &&
          mark.attrs.commentId === commentId
        ) {
          // 找到标记的完整范围
          // 标记可能跨越多个节点，需要找到连续的范围
          let markFrom = pos;
          let markTo = pos + node.nodeSize;

          // 向前查找标记的开始位置
          let checkPos = pos;
          while (checkPos > 0) {
            const prevResolved = state.doc.resolve(checkPos - 1);
            const prevMarks = prevResolved.marks();
            const hasSameMark = prevMarks.some(
              (m) =>
                m.type.name === "comment" &&
                m.attrs.commentId === commentId
            );
            if (hasSameMark) {
              markFrom = checkPos - 1;
              checkPos = checkPos - 1;
            } else {
              break;
            }
          }

          // 向后查找标记的结束位置
          checkPos = pos + node.nodeSize;
          while (checkPos < state.doc.content.size) {
            const nextResolved = state.doc.resolve(checkPos);
            const nextMarks = nextResolved.marks();
            const hasSameMark = nextMarks.some(
              (m) =>
                m.type.name === "comment" &&
                m.attrs.commentId === commentId
            );
            if (hasSameMark) {
              markTo = checkPos;
              checkPos = checkPos + 1;
            } else {
              break;
            }
          }

          // 检查这个范围是否已经添加过（避免重复）
          const isDuplicate = ranges.some(
            (r) => r.from === markFrom && r.to === markTo
          );
          if (!isDuplicate) {
            ranges.push({ from: markFrom, to: markTo });
          }
        }
      });
    }
  });

  // 从后往前移除标记，避免位置偏移问题
  if (ranges.length > 0) {
    ranges
      .sort((a, b) => b.from - a.from)
      .forEach(({ from, to }) => {
        tr.removeMark(from, to, commentMarkType);
      });

    editor.view.dispatch(tr);
  }
}

/**
 * 移除所有批注标记
 */
export function removeAllCommentMarks(editor: Editor): void {
  const { state } = editor;
  const { tr } = state;

  state.doc.descendants((node, pos) => {
    if (node.isText) {
      node.marks.forEach((mark) => {
        if (mark.type.name === "comment") {
          tr.removeMark(pos, pos + node.nodeSize, mark.type);
        }
      });
    }
  });

  editor.view.dispatch(tr);
}

/**
 * 更新批注标记的样式（不删除标记，只更新属性）
 */
export function updateCommentMarkStyle(
  editor: Editor,
  commentId: string,
  resolved: boolean
): void {
  const { state } = editor;
  const { tr } = state;

  state.doc.descendants((node, pos) => {
    if (node.isText) {
      node.marks.forEach((mark) => {
        if (
          mark.type.name === "comment" &&
          mark.attrs.commentId === commentId
        ) {
          // 移除旧标记
          tr.removeMark(pos, pos + node.nodeSize, mark.type);

          // 添加新标记（带 resolved 属性）
          const newMark = mark.type.create({
            ...mark.attrs,
            resolved,
          });
          tr.addMark(pos, pos + node.nodeSize, newMark);
        }
      });
    }
  });

  editor.view.dispatch(tr);
}

/**
 * 高亮编辑器中的批注标记（通过DOM操作添加active class）
 */
export function highlightCommentMark(
  editor: Editor,
  commentId: string | null
): void {
  const editorElement = editor.view.dom;
  if (!editorElement) return;

  // 移除所有批注标记的 active class
  const allCommentMarks = editorElement.querySelectorAll(
    '[data-comment-id]'
  ) as NodeListOf<HTMLElement>;
  allCommentMarks.forEach((mark) => {
    mark.classList.remove("active");
  });

  // 如果指定了 commentId，为对应的批注标记添加 active class
  if (commentId) {
    const targetMarks = editorElement.querySelectorAll(
      `[data-comment-id="${commentId}"]`
    ) as NodeListOf<HTMLElement>;
    targetMarks.forEach((mark) => {
      mark.classList.add("active");
    });
  }
}

/**
 * 滚动编辑器视图到指定批注位置
 */
export function scrollToCommentPosition(
  editor: Editor,
  from: number,
  to: number
): void {
  const { state, view } = editor;
  const { doc } = state;

  // 检查位置是否在有效范围内
  const docSize = doc.content.size;
  if (from < 0 || from > docSize || to < 0 || to > docSize) {
    console.warn(
      `批注位置超出文档范围: from=${from}, to=${to}, docSize=${docSize}`
    );
    return;
  }

  // 确保 from <= to
  const safeFrom = Math.max(0, Math.min(from, docSize));
  const safeTo = Math.max(0, Math.min(to, docSize));

  try {
    // 获取DOM坐标
    const startCoords = view.coordsAtPos(safeFrom);
    const endCoords = view.coordsAtPos(safeTo);

    // 获取编辑器容器
    const editorContainer = view.dom.closest(
      ".editor-content"
    ) as HTMLElement;
    if (!editorContainer) return;

    // 计算需要滚动的距离
    const containerRect = editorContainer.getBoundingClientRect();
    const targetTop = startCoords.top;
    const containerTop = containerRect.top;
    const scrollTop = editorContainer.scrollTop;

    // 如果目标位置不在视口内，滚动到可见
    if (
      targetTop < containerTop ||
      targetTop > containerTop + containerRect.height
    ) {
      const targetScrollTop = scrollTop + (targetTop - containerTop - 100); // 留出100px的顶部空间
      editorContainer.scrollTo({
        top: Math.max(0, targetScrollTop),
        behavior: "smooth",
      });
    }
  } catch (error) {
    console.warn("滚动到批注位置失败:", error);
    // 如果滚动失败，尝试使用简单的滚动方式
    try {
      editor.commands.scrollIntoView();
    } catch (e) {
      console.warn("备用滚动方式也失败:", e);
    }
  }
}
